﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Windows.ApplicationModel.Activation;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using System.Reactive.Linq;
using System.Reflection;
using Windows.UI.Xaml.Navigation;
using Windows.UI.Popups;

namespace JumpstartApp.Views
{
    using JumpstartApp.Helpers;
    using JumpstartApp.Models;

    using System.Diagnostics;

    public sealed partial class Splash : Page
    {
        public Splash(SplashScreen splashScreen)
        {
            Debug.WriteLine("Constructor");

            this.InitializeComponent();

            ArrangeImage(splashScreen);
            Window.Current.SizeChanged += (s, e) => ArrangeImage(splashScreen);

            Loaded += Splash_Loaded;
        }

        private void ArrangeImage(SplashScreen splashScreen)
        {
            this.MyImage.Height = splashScreen.ImageLocation.Height;
            this.MyImage.Width = splashScreen.ImageLocation.Width;
            this.MyImage.SetValue(Canvas.LeftProperty, splashScreen.ImageLocation.X);
            this.MyImage.SetValue(Canvas.TopProperty, splashScreen.ImageLocation.Y);
        }

        public Splash(LaunchActivatedEventArgs args)
            : this(args.SplashScreen)
        {
            PreviousExecutionState = args.PreviousExecutionState;
            if ((args.TileId ?? string.Empty) == "App")
            {
                this.GotoType = typeof(AppHub);
                this.GotoParam = null;
                this.AllowResume = true;
            }
            else
            {
                this.GotoType = typeof(Views.Detail);
                this.GotoParam = args.TileId;
                this.AllowResume = false;
            }
        }

        public Splash(ProtocolActivatedEventArgs args)
            : this(args.SplashScreen)
        {
            var _Decoder = new WwwFormUrlDecoder(args.Uri.Query);
            var _Id = _Decoder.Where(q => q.Name.ToLower() == "module").Select(q => q.Value).FirstOrDefault();
            if (string.IsNullOrWhiteSpace(_Id))
                _Decoder.Where(q => q.Name.ToLower() == "episode").Select(q => q.Value).FirstOrDefault();
            if (string.IsNullOrWhiteSpace(_Id))
            {
                Services.Navigation.GotoFail("The Uri specified was incorrect.");
                return;
            }
            AllowResume = false;
            GotoType = typeof(Views.Detail);
            GotoParam = _Id;
        }

        public Splash(SearchActivatedEventArgs args)
            : this(args.SplashScreen)
        {
            AllowResume = false;
            this.GotoType = typeof(Contracts.Search);
            this.GotoParam = args.QueryText;
        }

        public Splash(Type type, string param)
        {
            this.InitializeComponent();
            AllowResume = false;
            this.GotoType = type;
            this.GotoParam = param;
        }

        public static void SetupTheme(bool reload = true)
        {
            var _ColorString = StorageHelper.GetSetting(Contracts.Settings.PrimaryColor, Contracts.Settings.DefaultColor);

            Uri _Path = null;
            if (_ColorString.Equals(Windows.UI.Colors.Red.ToString()))
                _Path = new Uri("ms-appx:/Styles/CustomStyles.Red.xaml");
            else if (_ColorString.Equals(Windows.UI.Colors.Green.ToString()))
                _Path = new Uri("ms-appx:/Styles/CustomStyles.Green.xaml");
            else if (_ColorString.Equals(Windows.UI.Colors.Blue.ToString()))
                _Path = new Uri("ms-appx:/Styles/CustomStyles.Blue.xaml");
            else if (_ColorString.Equals(Windows.UI.Colors.Orange.ToString()))
                _Path = new Uri("ms-appx:/Styles/CustomStyles.Orange.xaml");

            var _Standard = new ResourceDictionary { Source = new Uri("ms-appx:/Styles/StandardStyles.xaml") };
            var _Custom = new ResourceDictionary { Source = _Path };
            var _Main = new ResourceDictionary { MergedDictionaries = { _Standard, _Custom } };
            foreach (var item in App.Current.Resources)
            {
                if (!_Main.ContainsKey(item.Key))
                    _Main.Add(item);
            }
            App.Current.Resources = _Main;

            // refresh the style immediately
            if (reload)
                Services.Navigation.Reload();
        }

        async void Splash_Loaded(object sender, RoutedEventArgs args)
        {
            Debug.WriteLine("Splash_Loaded");

            // wait for log actions
            await LogRunningActions();

            // create the frame
            Debug.WriteLine("Create Frame");
            var _Frame = Services.Navigation.Frame;

            // resuming? use previous
            Debug.WriteLine("Resume State");
            if (this.AllowResume
                && PreviousExecutionState == ApplicationExecutionState.Terminated)
                Services.Navigation.RestoreState();

            // not resuming or can't resume? use derived
            if (_Frame.Content == null)
            {
                Debug.WriteLine("Goto Hub (default)");
                _Frame.Navigate(GotoType ?? typeof(AppHub), GotoParam);
            }

            Debug.WriteLine("Activate");
            Window.Current.Activate();
        }

        private static async System.Threading.Tasks.Task LogRunningActions()
        {
            try
            {
                Debug.WriteLine("Login Start");
                if (Contracts.Settings.AllowLogin)
                {
                    var _Result = await Helpers.LiveSdk.LoginAsync(false);
                    if (!_Result.HasValue)
                    {
                        Debug.WriteLine("Login-Error");
                        await new MessageDialog("Error logging in").ShowAsync();
                    }
                    else if (_Result.Value)
                    {
                        Debug.WriteLine("Login-Success");
                        /* success */
                    }
                    else
                    {
                        Debug.WriteLine("Login-Deny");
                        // TODO: handle fail
                    }
                }
                else
                {
                    Debug.WriteLine("Login Settings=Off");
                }
            }
            catch (Exception) { throw; }

            // setup colors/style/theme
            Debug.WriteLine("Setup Theme");
            SetupTheme(false);

            // setup search
            Debug.WriteLine("Setup Search");
            Windows.ApplicationModel.Search.SearchPane.GetForCurrentView().ShowOnKeyboardInput = true;
            Windows.ApplicationModel.Search.SearchPane.GetForCurrentView().PlaceholderText = "Technical Topic";
            Windows.ApplicationModel.Search.SearchPane.GetForCurrentView().ResultSuggestionChosen +=
                (s, e) => Services.Navigation.GotoDetail(e.Tag);
            Windows.ApplicationModel.Search.SearchPane.GetForCurrentView().QuerySubmitted +=
                (s, e) => Services.Navigation.GotoSearch(e.QueryText);
            System.Reactive.Linq.Observable
                  .FromEventPattern<Windows.ApplicationModel.Search.SearchPaneSuggestionsRequestedEventArgs>(
                      Windows.ApplicationModel.Search.SearchPane.GetForCurrentView(), "SuggestionsRequested")
                  .Throttle(TimeSpan.FromMilliseconds(500), System.Reactive.Concurrency.Scheduler.CurrentThread)
                  .Where(x => x.EventArgs.QueryText.Length > 3)
                  .DistinctUntilChanged(x => x.EventArgs.QueryText.Trim())
                  .Subscribe(x => ViewModels.SearchViewModel.Suggest(x.EventArgs));

            // setup settings
            Debug.WriteLine("Setup Settings");
            var _Helper = new Helpers.SettingsHelper();
            _Helper.AddCommand<Contracts.Settings>("Settings");
            _Helper.AddCommand<Contracts.About>("About");

            // Load data from SkyDrive
            Debug.WriteLine("Get Notes");
            await EpisodeNotes.GetNotes();
        }

        public Type GotoType { get; set; }
        public string GotoParam { get; set; }
        public ApplicationExecutionState PreviousExecutionState { get; set; }
        public bool AllowResume { get; set; }
    }
}
